﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ALDIOrganizer.Properties;

namespace ALDIOrganizer
{
    public partial class MainForm
    {
        public void LoadRota(Rota pRota)
        {
            if (CurrentTemplate != null)
            {
                CurrentTemplate.OKLeaving();
            }
            svRota.DeactivateEvents();
            svRota.Visible = false;
            svTemplate.DeactivateEvents();

            #region rota
            CurrentRota = pRota;
            AdjustcbWeekValue();            
            tbCellNotesOrHoliday.BackColor = Program.CurrentTheme.GetColour(Theme.AnyNotes).BackColour.Value;
            tbCellNotesOrHoliday.ForeColor = Program.CurrentTheme.GetColour(Theme.AnyNotes).ForeColour.Value;
            svRota.Bind(CurrentRota, false); // it should display it
            svRota.Display(); // it refreshes the Employees AGAIN
                        
            CurrentRota.OnModifiedChanged += CurrentRota_OnModifiedChanged;
            CurrentRota_OnModifiedChanged(false);
            CurrentRota.OnViolatingRequest += CurrentRota_OnViolatingRequest;
            CurrentRota.OnShuttingDayWithShifts += CurrentRota_OnShuttingDayWithShifts;
            CurrentRota.OnLeavingModifiedEntity += IsUserOKWithLeavingCurrentRota;
            CurrentTemplate_OnModifiedChanged(false);
            #endregion
            
            LoadTemplate(Program.CurrentFile.GetTemplateCopy(CurrentRota.TemplateName));
            svRota.ActivateEvents();                        

            btnPrev.Enabled = Program.CurrentFile.IsPreviousExistingAndAccessible(CurrentRota);            
            btnNext.Enabled = Program.CurrentFile.IsNextExistingAndAccessible(CurrentRota);
            svRota.Visible = true;
            svRota.Refresh();
            svRota.ReadOnly = !Program.Logged.CanEditRota(CurrentRota.Monday);
            btnGenerate.Enabled = !svRota.ReadOnly;
            btnInventories.Enabled = !svRota.ReadOnly;
            btnShutDays.Enabled = !svRota.ReadOnly;
        }

        Discrepancies CurrentDiscrepancy
        {
            get
            {                
                if (CurrentRota == null ||
                    CurrentRota.GetAllShifts.Count() == 0 ||
                    CurrentTemplate == null ||
                    CurrentTemplate.GetAllCells.Count() == 0)
                {
                    return Discrepancies.NotApplicable;
                }
                return (CurrentRota.AnyOddShifts ||
                    CurrentTemplate.AnyOddShifts) ?
                    Discrepancies.Some :
                    Discrepancies.None;
            }
        }

        public void LoadTemplate(Template pTemplate)
        {
            svTemplate.DeactivateEvents();
            CurrentTemplate = pTemplate;
            CurrentTemplate.SetParent(CurrentTemplate);            
            CurrentTemplate.OnLeavingModifiedEntity += IsUserOKWithLeavingCurrentTemplate;
            svTemplate.OnRefreshTotalHours += sheetTempRota_OnRefreshTotalHours;            
            svTemplate.Bind(
                CurrentTemplate,
                true);
            svTemplate.Display();
            AdjustSheetTempRotaHeight();

            CurrentTemplate.OnModifiedChanged += CurrentTemplate_OnModifiedChanged;
            CurrentTemplate.OnWorkingHoursUpdated += CurrentTemplate_OnWorkingHoursUpdated;
            sheetTempOpeningHrs.Bind(
                CurrentTemplate,
                svTemplate);
            svTemplate.ActivateEvents();
            svTemplate.Refresh();
            TemplateComboboxRefreshState();
            
        }

        /// <summary>
        /// Forces the cbTemplate combobox to display the name of actually selected template
        /// </summary>
        /// <remarks>
        /// That combobox doesn't "know" whether the value is being changed programmatically
        /// or manually (by our user) - its SelectedIndexChanged will be triggered anyway.
        /// To avoid it, we set its Tag to true; When its Tag is true, SelextedIndexChanged
        /// event handler is supressed.
        /// </remarks>
        void TemplateComboboxRefreshState()
        {
            cbTemplate.Tag = true;
            cbTemplate.GoTo(CurrentTemplate.Name);
            cbTemplate.Tag = false;
        }


        void LoadDefaultRota()
        {
            var _default = Program.CurrentFile.rotas[DefaultRotaMonday()];
            PerformAction(_default,
                _default.ProperAction);
            UpdateTitlebar();
        }

        void ChangeTemplate(string pTemplateName)
        {
            LoadTemplate(Program.CurrentFile.GetTemplateCopy(pTemplateName));
            CurrentRota.SetTemplate(
                CurrentTemplate.Name,
                CurrentTemplate.WorkingHours);
            Sounds.Play(Sounds.Validated);
        }

        /// <summary>
        /// Selects 
        /// </summary>
        /// <returns>
        /// The suggestion given is the first match from that list, in that order of preference:
        /// 1.  rota for current week. [if not present...]        
        /// 2.  rota for the week after. [if not present...]
        /// 3.  the one closest to the current week
        /// </returns>
        static DateTime DefaultRotaMonday()
        {
            if (Program.CurrentFile.CurrentRota != null)
                return Program.CurrentFile.CurrentRota.Monday;
            return Program.CurrentFile.NextRota != null ?
                Program.CurrentFile.NextRota.Monday :
                Program.CurrentFile.rotas.Keys.Closest(DateTime.Today);
        }
   

        void tbCellNotesOrHoliday_MouseDown(object sender, MouseEventArgs e)
        {
            btnNotes.Focus();
        }

        void sheetRota_OnCellEntered(Cell pCell)
        {
            #region suspending layouts
            tblCellSummary.SuspendLayout();
            lbThisCell.SuspendLayout();
            tbCellNotesOrHoliday.SuspendLayout();
            #endregion

            lbThisCell.Text = pCell.ToStringForMainForm();
            tbCellNotesOrHoliday.Text = String.Empty;

            if (pCell.HasAnyNotes)
            {
                tbCellNotesOrHoliday.Text = pCell.Notes;
            }
            if (pCell.MyCellType == CellType.Holiday)
            {
                var holiday = new Holiday(SQLiteAccess.GetHolidays(pCell.GetStatusID[0]));
                tbCellNotesOrHoliday.Text = holiday.FullDescription() +
                    ((holiday.comments.Length > 0) ?
                    String.Concat("(", holiday.comments, ")") :
                    String.Empty);
            }
            if (pCell.HasAnyRequests)
            {
                tbCellNotesOrHoliday.Text = String.Join(
                    "; ",
                    (from request in pCell.GetMyRequests
                     where request.Comments != String.Empty
                     select request.Comments).ToArray());
            }            

            #region resuming layouts
            lbThisCell.ResumeLayout();
            tbCellNotesOrHoliday.ResumeLayout();
            tblCellSummary.ResumeLayout();
            #endregion
            
        }

        void WhenTemplateIsModified(Rota pRota, Template pTemplate)
        {
            
            Program.reactToTemplateModificationForm = new TemplateModificationReaction(pRota,
                pTemplate);
            Program.reactToTemplateModificationForm.ShowDialog();
            var decision = Program.reactToTemplateModificationForm.Result;
            
            if (decision == TemplateDecision.Rename)
            {
                var newName = Program.reactToTemplateModificationForm.DecidedAlternativeName;
                Program.CurrentFile.ReuniteWithDatabase(CurrentTemplate);
                CurrentTemplate.Name = newName;
                CurrentRota.SetTemplate(
                    CurrentTemplate.Name,
                    CurrentTemplate.WorkingHours);
                Program.CurrentFile.RecalculateRotasBasedOn(CurrentTemplate.Name);
                Program.CurrentFile.ReuniteWithDatabase(CurrentTemplate); // new version this Time!
                cbTemplate.Tag = true;
                cbTemplate.GoTo(newName);
                cbTemplate.Tag = false;
            }
            if (decision == TemplateDecision.ModifyExisting)
            {
                Program.CurrentFile.ReuniteWithDatabase(CurrentTemplate);
                Program.CurrentFile.RecalculateRotasBasedOn(CurrentTemplate.Name);
            }

            Program.reactToTemplateModificationForm.Dispose();
        }

        void CreateNewTemplate()
        {
            Template newTemplate;

            Program.inputTemplateNameForm = new formInputTemplateName(String.Empty);
            if (Program.inputTemplateNameForm.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            var newName = Program.inputTemplateNameForm.Result;
            string parentName;

            if (Program.CurrentFile.AnyChoiceOfTemplates)
            {
                Program.frmChooseBaseTemplate = new ChooseTemplate(
                    Resources.FORM_CHOOSETEMPLATE_GroupBoxCaption_CreateTemplate,
                    true);
                if (Program.frmChooseBaseTemplate.ShowDialog() == DialogResult.OK)
                {
                    parentName = Program.frmChooseBaseTemplate.GetChoice;
                }
                else
                {
                    return;
                }
            }
            else
            {
                parentName = Template.DefaultName;
            }

            // if user chose not to base the new template On any existing one (but Start from scratch)
            if (parentName == String.Empty)
            {
                // we need to use SOME working hours. we take them from default template
                var hours = Program.CurrentFile.templates[Template.DefaultName].WorkingHours;
                newTemplate = new Template(
                    hours,
                    newName);
                newTemplate.SetParent(newTemplate);
            }
            // else: if user chose to base new template on one of the existing ones
            else
            {                    
                newTemplate = Program.CurrentFile.GetTemplateCopy(parentName);
                // no need to call SetParent - DeepCopy (used by GetTemplateCopy) has done it for us by now
                newTemplate.Name = newName;
            }
                                
            Program.CurrentFile.ReuniteWithDatabase(newTemplate);
                
            MessageBox.Show(                
                Resources.MESSAGEBOX_INFO_NewTemplateAdded_Message.Replace(
                    "#", newName),
                Resources.MESSAGEBOX_INFO_NewTemplateAdded_Caption.Replace(
                    "#", newName),
                MessageBoxButtons.OK,
                MessageBoxIcon.Information);
                    
            Hourglass(true);
            cbTemplate.GoTo(newName);
            Sounds.Play(Sounds.Validated); 
            Hourglass(false);
        }

        void SaveSheet(SheetView pDataGrid)
        {
            if (pDataGrid.refill == null)
            {
                return;
            }
            Hourglass(true);
            pDataGrid.DeactivateEvents();
            Program.CurrentFile.ReuniteWithDatabase(pDataGrid.refill);
            pDataGrid.refill.Modified = false;
            pDataGrid.ActivateEvents();
            Sounds.Play(Sounds.Validated); 
            Hourglass(false);
        }

        void SaveRota()
        {
            SaveSheet(svRota);            
        }

        void SaveTemplate()
        {
            SaveSheet(svTemplate);
        }

        void DeleteTemplate(string pName)
        {
            svTemplate.DeactivateEvents();
            var areYouSure = MessageBox.Show(
               Resources.MESSAGEBOX_QUESTION_DeleteTemplate_MESSAGE.Replace(
               "#", pName),
               Resources.MESSAGEBOX_QUESTION_DeleteTemplate_CAPTION,                              
               MessageBoxButtons.YesNo,
               MessageBoxIcon.Question);
            if (areYouSure == DialogResult.No)
            {
                return;
            }
            if (pName != CurrentTemplate.Name)
            {
                Program.CurrentFile.DeleteTemplate(pName);
                return;
            }
            
            cbTemplate.GoTo(Template.DefaultName);
            Program.CurrentFile.DeleteTemplate(pName);
            svTemplate.ActivateEvents();
        }

        private void sheetRota_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
        {
            // 
            layoutAdjustWidthOfSheets(true);
        }

        private void cbWeek_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbWeek.Tag.GetType() == typeof(bool))
            {
                if ((bool)cbWeek.Tag)
                {
                    return; // ignore selected value changed
                }
            }
            if (cbWeek.SelectedValue == null)
            {
                return;
            }
            if (cbWeek.SelectedValue.GetType() != typeof(DateTime))
            {
                return;
            }
            var _date = (DateTime)cbWeek.SelectedValue;
            var _target = Program.CurrentFile.rotas[_date];
            if (_target.ProperAction == RotaAction.None)
            {
                // we cancel
                AdjustcbWeekValue(); // reset the value to previous one
                return;
            }
            PerformAction(_target, _target.ProperAction);
        }
    }
}
